第五章 终端

在学习本章节的时候,我遇到了一些困难,主要是因为 CentOS7 没有默认安装 curses 开发包和 term 开发包(集成进 curses )。

因此需要:

  1. 安装开发包:yum install ncurses-devel.x86_64

  2. 编译时加入 -lncurses 选项


对终端进行读写

标准模式和非标准模式

默认情况下,只有用户按下回车键后,程序才能读到终端的输入。这方便了使用删除键来纠正输入错误,用户觉得输入满意后,才按下回车传递数据给程序。

这种方式被称为标准模式。所有输入都基于行进行处理,在一个输入行完成前,终端接口负责管理所有键盘输入,应用程序读不到用户输入的任何字符。

还有一种模式是非标准模式,应用程序对用户输入字符的处理拥有更大的控制权。

除此之外,终端能够把中断字符转换为对应的新号(发送给程序)。

处理重定向输出

Linux 程序经常会把它们的输入或输出重定向到文件或其他程序。但有时候我们并不想这样做,比如一个菜单程序,没有必要把菜单的打印重定向。

可以使用 isatty 函数来检查标准输出是否被重定向了。它判断的是某一个文件描述符是否连接到了一个终端。

与终端进行对话

可以直接对终端进行读写,而不是通过标准输入输出。方法是使用特殊设备/dev/tty。该设备始终指向当前终端或当前的登录会话。 Linux 把一切事物都看作文件,所以可以用一般文件的操作方式来对 /dev/tty进行读写。

终端驱动程序和通用终端接口

Linux 提供了一组编程接口来控制终端驱动程序的行为。

下面是能够控制的主要功能:

termios 结构

termios 是在 POSIX 规范中定义的标准接口,通过设置 termios 类型的数据结构中的值和使用一小组函数调用,你就可以对终端接口进行控制。它们都定义在头文件 termios.h 中。

通过 tcgetattr 和 tcsetattr 来获取/设置 termios 结构。

使用这些接口的时候,很容易忘记把模式重置为标准模式,从而导致终端的使用出现问题,输入下面的命令解决:

$ stty sane

Note

或者直接重启终端,把之前的设置丢弃掉就行了。

还可以在命令提示符下设置终端的模式,即通过 stty 命令。

比如:

# 取消掉回显
$ stty -echo

终端的输出

终端的类型

“终端”可能指的是 PC 上运行的一个终端仿真程序或者窗口环境中的一个终端应用程序。

终端几乎都使用 escape 转义序列来控制光标的位置和其他属性,比如黑体和闪烁等。这些序列有许多标准。

使用 terminfo 软件包统一了使用接口。它被继承在 curses 软件包中。使用它们需要引入 curses.h 和 term.h ,并加入 -lncurses 连接选项。

识别终端类型

环境变量 TERM 被设置为当前正在使用的终端类型。

terminfo 软件包包含一个由大量不同类型终端的功能标志和 escape 转义序列等信息构成的数据库,并且为使用它们提供了一个统一的编程接口。

每个 terminfo 定义由3种类型的数据项组成,每个数据项被称为 capname ,它们分别用于定义终端的一种功能标志。

使用 terminfo 功能标志

使用 terminfo 时,第一件事情就是调用 setupterm 来设置终端类型。

之后就可以查看当前终端的功能标志并使用它们的功能了。

通过 tigetflag tigetnum tigetstr 来查询终端的功能标志的值(布尔,数值,字符串)。

某些功能标志还需要参数,那么就要用到 tparm 函数生成转义序列。

接着,使用 putp 或者 tputs 函数将功能标志的值(或转义序列)发送给终端,从而可以完成诸如跳转光标这样的功能。

虚拟控制台

Linux 提供了虚拟控制台的功能,一组终端设备共享 PC 电脑的屏幕、键盘和鼠标,它们通过字符设备文件 /dev/ttyN 使用。N从1开始。

如果使用字符界面登陆 Linux 系统,这就是第一个虚拟控制台,即终端设备 /dev/tty1

使用 CTRL + ALT + F1 ~ F12 来切换到一个虚拟控制台。

使用 who 命令可以查询目前进系统的用户以及用的是何种终端。